﻿using System;
using System.ComponentModel;
using System.Windows.Documents;
using Notoric.Gui.Windows;

namespace Notoric.Gui.Commands
{
    /// <summary>
    /// Implements a command for setting a new font size to an active selection
    /// in a <see cref="ViewModel.Elements.RtfTextSectionInterior"/>.
    /// </summary>
    public class SetFontSizeCommand : RtfTextSelectionCommand
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="SetFontSizeCommand"/> class.
        /// </summary>
        /// <param name="mainWindow">
        /// <para>
        /// Type: <see cref="MainWindow"/>
        /// </para>
        /// <para>
        /// The main application window.
        /// </para>
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// The <paramref name="mainWindow"/> is <see langword="null"/>.
        /// </exception>
        public SetFontSizeCommand(MainWindow mainWindow)
            : base(mainWindow)
        {
            DependencyPropertyDescriptor prop = DependencyPropertyDescriptor.FromProperty(Fluent.ComboBox.CurrentTextProperty, typeof(Fluent.ComboBox));
            prop.AddValueChanged(ApplicationWindow.comboBoxFontSize, new EventHandler(comboBoxFontSize_CurrentTextChanged));
        }

        #endregion
        
        #region RtfTextSelectionCommand Members

        /// <inheritdoc/>
        protected override bool CanExecuteCore(object parameter)
        {
            return interior != null && interior.Selection != null;
        }

        /// <inheritdoc/>
        protected override void SelectionChanged(ViewModel.Elements.RtfTextSectionInterior interior)
        {
            this.interior = interior;
            if (interior != null)
            {
                var selection = interior.Selection;
                var value = (selection != null ? selection.GetPropertyValue(TextElement.FontSizeProperty) : null);

                isWritingValueBack = true;
                ApplicationWindow.comboBoxFontSize.CurrentText = (value != null ? Math.Round((double)value * (96 / 72)).ToString() : "");
                isWritingValueBack = false;
            }
            base.SelectionChanged(interior);
        }

        #endregion

        #region ICommand Members

        /// <inheritdoc/>
        public override void Execute(object parameter)
        {
            if (isWritingValueBack || interior == null || interior.Selection == null)
                return;

            int pointValue;

            try
            {
                pointValue = int.Parse(ApplicationWindow.comboBoxFontSize.CurrentText);
            }
            catch (Exception)
            {
                return;
            }

            double value = pointValue / (96 / 72);
            var selection = interior.Selection;

            var cmd = new ViewModel.SetFormatPropertyCommand(ApplicationWindow.StackManager.ActiveUndoStack, ApplicationWindow.StackManager.ActiveRedoStack)
            {
                Property = TextElement.FontSizeProperty,
                Selection = selection,
                Value = value
            };

            cmd.Execute(null);
            interior.Selection = selection;
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the user inputs a new font size.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void comboBoxFontSize_CurrentTextChanged(object sender, EventArgs e)
        {
            if (!isWritingValueBack)
                Execute(null);
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Indicates whether the command is currently writing the selection
        /// value back to the font size combo box.
        /// </summary>
        private bool isWritingValueBack;
        /// <summary>
        /// Holds the current selection.
        /// </summary>
        private ViewModel.Elements.RtfTextSectionInterior interior;

        #endregion
    }
}